package mylibrary.security.DSA;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;

public class DSACoder {

	public static final String ALGORITHM = "DSA";
	
	public static final String SIGNATURE_ALGORITHM = "SHA1withDSA";
	
	private static final String PUBLIC_KEY = "DSAPublicKey";
	private static final String PRIVATE_KEY = "DSAPrivateKey";
	private static final int KEY_SIZE = 1024;
	
	public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
		
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(priKey);
		signature.update(data);
		return signature.sign();
	}
	
	public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(privateKey);
		signature.update(data);
		return signature.sign();
	}
	
	public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		PublicKey pubKey = keyFactory.generatePublic(keySpec);
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(pubKey);
		signature.update(data);
		return signature.verify(sign);
	}
	
	public static boolean verify(byte[] data, PublicKey publicKey, byte[] sign) throws Exception {
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(publicKey);
		signature.update(data);
		return signature.verify(sign);
	}
	
	public static Map initKey() throws Exception {
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
		keyGen.initialize(KEY_SIZE, new SecureRandom());
		KeyPair keys = keyGen.generateKeyPair();
		DSAPublicKey publicKey = (DSAPublicKey)keys.getPublic();
		DSAPrivateKey privateKey = (DSAPrivateKey)keys.getPrivate();
		
		Map map = new HashMap();
		map.put(PUBLIC_KEY, publicKey);
		map.put(PRIVATE_KEY, privateKey);
		
		return map;
	}
	
	public static void main(String[] args) throws Exception {
		
		String str = "This is DSA";
		Map map = initKey();
		PrivateKey privateKey = (PrivateKey) map.get(PRIVATE_KEY);
		PublicKey publicKey = (PublicKey) map.get(PUBLIC_KEY);
		System.out.println("privateKey=" + Base64.encodeBase64String(privateKey.getEncoded()));
		System.out.println("publicKey=" + Base64.encodeBase64String(publicKey.getEncoded()));
		
		byte[] sign = sign(str.getBytes(), privateKey);
		System.out.println("sign=" + Base64.encodeBase64String(sign));
		
		boolean status = verify(str.getBytes(), publicKey, sign);
		System.out.println(status);
	}
}
